package com.github.yealove.configgen.web;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.github.yealove.configgen.dto.R;
import com.github.yealove.configgen.model.Config;
import com.github.yealove.configgen.model.NacosItem;
import com.github.yealove.configgen.model.Result;
import com.github.yealove.configgen.model.Template;
import com.github.yealove.configgen.service.*;
import com.github.yealove.configgen.utils.IpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Slf4j
@RestController
public class ConfigGenController {

    @Value("${file.path:D\\temp}")
    private String path;

    @Autowired
    private GroupService groupService;

    @Autowired
    private ConfigService configService;

    @Autowired
    private TemplateService templateService;

    @Autowired
    private ResultService resultService;

    @Autowired
    private NacosService nacosService;

    /**
     * 获取参数组列表
     *
     * @return 参数组集合
     */
    @GetMapping("groups")
    public R getAllGroup() {
        return R.success(groupService.getAllGroup());
    }

    /**
     * 新增参数组
     *
     * @param name 参数组名称
     * @return 新增结果
     */
    @PostMapping("groups/{name}")
    public R addGroup(@PathVariable String name) {
        groupService.addGroup(name);
        return R.success();
    }

    /**
     * 获取组内参数配置
     *
     * @param gid 组ID
     * @return 参数配置集合
     */
    @GetMapping("configs/group/{gid}")
    public R<List<Config>> getConfigs(@PathVariable("gid") int gid) {
        return R.success(configService.getByGid(gid));
    }

    /**
     * 保存参数组配置
     *
     * @param gid     参数组ID
     * @param configs 参数列表
     * @return 保存结果
     */
    @PostMapping(value = "configs/group/{gid}")
    public R saveConfigs(@PathVariable int gid, @RequestBody List<Config> configs) {
        configService.saveConfigs(gid, configs);
        return R.success();
    }

    /**
     * 从模板解析
     *
     * @param gid 参数组ID
     * @param tids 模板ID集合
     * @return 解析结果
     */
    @PostMapping(value = "configs/parse/{gid}")
    public R parseTemplateConfigs(@PathVariable int gid, @RequestBody List<Integer> tids) {
        configService.parseTemplate2Configs(gid, tids);
        return R.success();
    }

    /**
     * 获取模板列表
     *
     * @return 参数组集合
     */
    @GetMapping("templates")
    public R<List<Template>> getAllTemplate() {
        return R.success(templateService.getAllTemplate());
    }

    /**
     * 新增模板
     *
     * @param template 模板数据
     * @return 新增结果
     */
    @PostMapping("template")
    public R saveTemplate(@Validated @RequestBody Template template) {
        templateService.saveTemplate(template);
        return R.success();
    }

    /**
     * 生成配置文件
     *
     * @param groupId     参数组ID
     * @param templateIds 模板ID集合
     * @return 生成结果
     */
    @PostMapping("gen/{gId}")
    public R gen(@PathVariable("gId") int groupId, @RequestBody List<Integer> templateIds) {
        resultService.genResult(templateIds, groupId);
        return R.success();
    }

    /**
     * 查询生成结果
     *
     * @param search    查询条件
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 生成结果
     */
    @GetMapping("results")
    public R<List<Result>> getResults(@RequestParam(value = "search", required = false) String search,
        @RequestParam(value = "startTime", required = false) String startTime, @RequestParam(value = "endTime", required = false) String endTime) {
        return R.success(resultService.searchResult(search, startTime, endTime));
    }

    /**
     * 生成下载文件
     *
     * @param rIds 结果ID集合
     * @return 文件名
     */
    @PostMapping("download")
    public R download(@RequestBody List<Integer> rIds) {
        List<Result> results = resultService.getResultByIds(rIds);
        File folder = new File(path, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        folder.mkdir();

        for (Result result : results) {
            if(StringUtils.isNotBlank(result.getNacosGroup())) {
                result.setFileName(result.getNacosGroup() + "/" + result.getFileName());
            }
            File file = new File(folder, result.getFileName());
            FileUtil.writeString(result.getFileContent(), file, "UTF-8");
        }
        File file = ZipUtil.zip(folder);

        return R.success(file.getName());
    }

    /**
     * 清除生成结果
     *
     * @return 清除结果
     */
    @GetMapping("results/clear")
    public R clearResult() {
        resultService.clear();
        return R.success();
    }

    /**
     * 下载文件
     * @param fileName 文件名
     * @return 文件
     */
    @RequestMapping("/download/{fileName}")
    public ResponseEntity<InputStreamResource> downloadFile(@PathVariable String fileName) throws IOException {

        File file = new File(path, fileName);
        if (!file.exists()) {
            return ResponseEntity.noContent().build();
        }
        String mimeType = FileUtil.getMimeType(file.getPath());

        InputStreamResource resource = new InputStreamResource(new FileInputStream(file));

        return ResponseEntity.ok()
                // Content-Disposition
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())
                // Content-Type
                .contentType(MediaType.parseMediaType(mimeType))
                // Contet-Length
                .contentLength(file.length())
                .body(resource);
    }

    /**
     * 推送日志
     *
     * @param request   请求
     * @param nacosItem nacos配置
     * @return 推送结果
     */
    @PostMapping("/pushLog")
    public R pushLog(HttpServletRequest request, @RequestBody NacosItem nacosItem) {
        try {
            String ipAddr = IpUtil.getIpAddr(request);
            nacosItem.setCreateIp(ipAddr);
            resultService.addPushLog(nacosItem);
        } catch (Exception e) {
            log.error("保存推送日志失败", e);
        }
        return R.success();
    }

    /**
     * 获取nacos地址列表
     *
     * @return 地址列表
     */
    @GetMapping("/nacos-servers")
    public R<List<String>> getNacosServers() {
        return R.success(nacosService.getNacosServers());
    }

    /**
     * 保存nacos地址列表
     *
     * @param servers nacos地址列表
     * @return 保存结果
     */
    @PostMapping("/nacos-servers")
    public R saveNacosServers(@RequestBody List<String> servers) {
        nacosService.saveNacosServers(servers);
        return R.success();
    }
}
